package tenumn.energytech.registrys.item;

import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraft.core.NonNullList;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.client.IItemRenderProperties;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.EnergyStorage;
import org.jetbrains.annotations.Nullable;
import tenumn.energytech.EnergyTech;
import tenumn.energytech.registrys.capability.EnergyCapabilityProvider;

import javax.annotation.ParametersAreNonnullByDefault;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;

@ParametersAreNonnullByDefault
public abstract class ItemEnergy extends Item {
    public ItemEnergy(Properties pProperties) {
        super(pProperties);
    }

    public abstract int getMaxEnergyStorage();

    public abstract int getStateCount();

    @Nullable
    @Override
    public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundTag nbt) {
        return new EnergyCapabilityProvider(() -> new EnergyStorage(getMaxEnergyStorage()));
    }


    @Nullable
    @Override
    public CompoundTag getShareTag(ItemStack stack) {
        super.getShareTag(stack);
        var tag = stack.getOrCreateTag();
        stack.getCapability(CapabilityEnergy.ENERGY).ifPresent(iEnergyStorage -> {
            tag.putInt("FE", iEnergyStorage.getEnergyStored());
        });
        return tag;
    }

    @Override
    public void readShareTag(ItemStack stack, @Nullable CompoundTag nbt) {
        super.readShareTag(stack, nbt);
        if (nbt == null) {
            return;
        }
        stack.getCapability(CapabilityEnergy.ENERGY).ifPresent(iEnergyStorage -> {
            iEnergyStorage.receiveEnergy(nbt.getInt("FE"), false);
        });
    }

    @Override
    public void fillItemCategory(CreativeModeTab pCategory, NonNullList<ItemStack> pItems) {
        if (this.allowdedIn(pCategory)) {
            if (overrideItemCategory()) {
                pItems.add(withEnergy(0));
                pItems.add(withEnergy(getMaxEnergyStorage()));
            } else super.fillItemCategory(pCategory, pItems);
        }
    }

    protected boolean overrideItemCategory() {
        return true;
    }

    private ItemStack withEnergy(int energy) {
        ItemStack itemStack = new ItemStack(this);
        itemStack.getCapability(CapabilityEnergy.ENERGY).ifPresent(iEnergyStorage -> {
            iEnergyStorage.receiveEnergy(energy, false);
        });
        return itemStack;
    }

    @Override
    public int getBarWidth(ItemStack pStack) {
        AtomicInteger width = new AtomicInteger(1);
        pStack.getCapability(CapabilityEnergy.ENERGY).ifPresent(iEnergyStorage -> {
            width.set(Math.round(13 * ((float) iEnergyStorage.getEnergyStored() / (float) iEnergyStorage.getMaxEnergyStored())));
        });
        return width.get();
    }

    public static <T extends ItemEnergy> void addEnergyStates(T energy) {
        AtomicReference<Integer> result = new AtomicReference<>(0);
        int maxState = energy.getStateCount();
        ItemProperties.register(energy, new ResourceLocation(EnergyTech.ID, "energy_v" + maxState), (pStack, pLevel, pEntity, pSeed) -> {
            pStack.getCapability(CapabilityEnergy.ENERGY).ifPresent(iEnergyStorage -> {
                int div = 1 / maxState;
                for (int i = maxState; i > 0; i--) {
                    if (iEnergyStorage.getEnergyStored() > iEnergyStorage.getMaxEnergyStored() * (i - 1) * div) {
                        result.set(i - 1);
                        break;
                    }
                }
            });
            return result.get();
        });
    }


    @Override
    public void initializeClient(Consumer<IItemRenderProperties> consumer) {
        if (getStateCount() > 1) addEnergyStates(this);
    }

    @Override
    public int getBarColor(ItemStack pStack) {
        return 0XC_c_000______________0;
    }

    @Override
    public boolean isBarVisible(ItemStack pStack) {
        AtomicBoolean shouldShow = new AtomicBoolean(true);
        pStack.getCapability(CapabilityEnergy.ENERGY).ifPresent(iEnergyStorage -> {
            if (iEnergyStorage.getEnergyStored() == iEnergyStorage.getMaxEnergyStored()) shouldShow.set(false);
        });
        return shouldShow.get();
    }
}
